#include <sys/style.hpp>
#include <sys/asm.hpp>
#include <sys/allocator.hpp>
#include <river/iis.hpp>
#include <river/scheduler.hpp>
#include <global/var.hpp>
#include <global/irq.hpp>
#include <global/pic.hpp>
#include <global/exception.hpp>
#include <global/previlege.hpp>
#include <global/syscall.hpp>
#include <global/string.hpp>
#include <global/system.hpp>
void          IntInitService::init(){
  sgdt_asm(&gdtr);
  string::memcpy(&gdt, gdtr.addr, gdtr.len + 1);
  gdtr.len   =  gdt_size() * sizeof(descriptor) - 1;
  gdtr.addr  =  &gdt;
  idtr.len   =  idt_size() * sizeof(gate) - 1;
  idtr.addr  =  &idt;
  init_interrupt();
}
void          IntInitService::init_interrupt(){ 
  pic::init();
  for(int i=0,len=exception::size();i<len;i++){ 
    idt[i].init(exception::handler(i),previlege::kernel());
  }
  idt[3].init(exception::breakpoint,previlege::user());
  idt[4].init(exception::overflow,previlege::user());
  for(int i=0,len=irq::size();i<len;i++){
    idt[irq::intv_irq(i)].init(irq::handler(i),previlege::kernel());
  }
  idt[syscall::intv_sys_call()].init(syscall::sys_call,previlege::user());
  lidt_asm(&idtr);
  lgdt_asm(&gdtr);
}  
void          descriptor::init(type::u32 base, type::u32 limit, type::u16 attribute){
  limit_low		= limit & 0x0FFFF;		
  base_low		= base & 0x0FFFF;
  base_mid		= (base >> 16) & 0x0FF;
  attr1 		= attribute & 0xFF;		
  limit_high_attr2	= ((limit >> 16) & 0x0F) | ((attribute >> 8) & 0xF0);
  base_high		= (base >> 24) & 0x0FF;
}
void          gate::init(type::fptr handler,type::u32 privilege){
  type::u32	base	=  (type::u32)handler;
  offset_low	        =  base & 0xFFFF;
  selector	        =  CODE_SELECTOR;
  dcount         	=  0;
  attr		        =  0x008E | (privilege << 5);
  offset_high 	        =  (base >> 16) & 0xFFFF;
}
